<!-- 
 * @Description: 会话管理
 * @Author: huguodong 
 * @Date: 2023-12-15 15:45:10
!-->
<template>
  <div>
    <!-- 统计卡片 -->
    <StatsCard ref="statsCardRef" />
    <!-- 会话列表 -->
    <div class="table-box">
      <ProTable ref="proTable" :columns="columns" :init-param="initParam" :request-api="requestApi" :title="tableTitle">
        <!-- 表格 header 按钮 -->
        <template #tableHeader="scope">
          <el-space wrap>
            <el-radio-group v-model="clientType" @change="onClientTypeChange">
              <el-radio-button label="B">B端会话</el-radio-button>
              <el-radio-button label="C">C端会话</el-radio-button>
            </el-radio-group>
            <el-input v-model="initParam.searchKey" clearable placeholder="请输入用户账号或姓名" style="width: 250px" @clear="refreshTable">
              <template #append>
                <el-button :icon="Search" @click="refreshTable" />
              </template>
            </el-input>
            <s-button :disabled="!scope.isSelected" plain type="danger" @click="onBatchForceOffline(scope.selectedListIds)">
              <el-icon>
                <SwitchButton />
              </el-icon>
              批量下线
            </s-button>
            <s-button plain type="primary" @click="refreshTable">
              <el-icon>
                <Refresh />
              </el-icon>
              刷新
            </s-button>
          </el-space>
        </template>

        <!-- 用户信息 -->
        <template #userInfo="scope">
          <div class="user-info">
            <el-avatar v-if="scope.row.avatar" :size="40" :src="scope.row.avatar" />
            <el-avatar v-else :size="40">
              <el-icon>
                <User />
              </el-icon>
            </el-avatar>
            <div class="user-detail">
              <div class="user-name">{{ scope.row.name }}</div>
              <div class="user-account">{{ scope.row.account }}</div>
            </div>
          </div>
        </template>

        <!-- 登录信息 -->
        <template #loginInfo="scope">
          <div class="login-info">
            <div class="info-item">
              <el-icon>
                <Location />
              </el-icon>
              <span>{{ scope.row.latestLoginIp }} ({{ scope.row.latestLoginAddress }})</span>
            </div>
            <div class="info-item">
              <el-icon>
                <Clock />
              </el-icon>
              <span>{{ scope.row.latestLoginTime }}</span>
            </div>
          </div>
        </template>

        <!-- 令牌数量 -->
        <template #tokenCount="scope">
          <el-tag size="small" type="primary">{{ scope.row.tokenCount }} 个</el-tag>
        </template>

        <!-- 在线状态 -->
        <template #onlineStatus="scope">
          <el-tag v-if="scope.row.onlineStatus === 'ONLINE'" type="success">
            <el-icon class="is-loading">
              <Loading />
            </el-icon>
            在线
          </el-tag>
          <el-tag v-else type="info">离线</el-tag>
        </template>

        <!-- 操作 -->
        <template #operation="scope">
          <el-space>
            <s-button :opt="FormOptEnum.VIEW" link @click="onOpenDetail(scope.row)">详情</s-button>
            <s-button :opt="FormOptEnum.EDIT" link type="primary" @click="onManageToken(scope.row)">令牌管理</s-button>
            <s-button :opt="FormOptEnum.DELETE" link type="danger" @click="onForceOffline(scope.row.id, scope.row.name)"> 强退 </s-button>
          </el-space>
        </template>
      </ProTable>

      <!-- 会话详情 -->
      <Detail ref="detailRef" />

      <!-- Token管理 -->
      <TokenManager ref="tokenManagerRef" :client-type="clientType" @refresh="refreshTable" />
    </div>
  </div>
</template>

<script lang="ts" name="sessionMonitor" setup>
import { ColumnProps, ProTableInstance } from "@/components/ProTable/interface";
import { Clock, Loading, Location, Refresh, Search, SwitchButton, User } from "@element-plus/icons-vue";
import { Session, sessionApi } from "@/api";
import { FormOptEnum } from "@/enums";
import { useHandleData } from "@/hooks/useHandleData";
import { ElMessage } from "element-plus";
import StatsCard from "./components/statsCard.vue";
import Detail from "./components/detail.vue";
import TokenManager from "./components/tokenManager.vue";

// 表格初始化参数
interface InitParam {
  searchKey?: string;
}

const initParam = reactive<InitParam>({});

// 客户端类型
const clientType = ref<"B" | "C">("B");

// 获取 ProTable 元素
const proTable = ref<ProTableInstance>();
const statsCardRef = ref<InstanceType<typeof StatsCard> | null>(null);

// 表格标题
const tableTitle = computed(() => {
  return clientType.value === "B" ? "B端在线会话" : "C端在线会话";
});

// 请求API
const requestApi = computed(() => {
  return clientType.value === "B" ? sessionApi.pageB : sessionApi.pageC;
});

// 表格配置项
const columns: ColumnProps<Session.SessionInfo>[] = [
  { type: "selection", fixed: "left", width: 50 },
  { prop: "userInfo", label: "用户信息", width: 200 },
  { prop: "loginInfo", label: "登录信息", minWidth: 300 },
  { prop: "tokenCount", label: "令牌数量", width: 100 },
  { prop: "onlineStatus", label: "在线状态", width: 100 },
  { prop: "operation", label: "操作", width: 250, fixed: "right" }
];

// 详情引用
const detailRef = ref<InstanceType<typeof Detail> | null>(null);
const tokenManagerRef = ref<InstanceType<typeof TokenManager> | null>(null);

/**
 * 客户端类型切换
 */
function onClientTypeChange() {
  refreshTable();
}

/**
 * 打开详情
 * @param record 记录
 */
function onOpenDetail(record: Session.SessionInfo) {
  detailRef.value?.onOpen(record);
}

/**
 * 打开Token管理
 * @param record 记录
 */
function onManageToken(record: Session.SessionInfo) {
  tokenManagerRef.value?.onOpen(record);
}

/**
 * 强制下线
 * @param id 用户ID
 * @param name 用户姓名
 */
async function onForceOffline(id: number, name: string) {
  const api = clientType.value === "B" ? sessionApi.exitSessionB : sessionApi.exitSessionC;
  await useHandleData(api, id, `强退【${name}】`);
  refreshTable();
}

/**
 * 批量强制下线
 * @param ids 用户ID数组
 */
async function onBatchForceOffline(ids: any) {
  if (!ids || ids.length === 0) {
    ElMessage.warning("请选择要强退的会话");
    return;
  }
  // 转换为number数组
  const numIds = ids as unknown as number[];
  const api = clientType.value === "B" ? sessionApi.batchExitSessionB : sessionApi.batchExitSessionC;
  await useHandleData(api, { ids: numIds }, `批量强退${numIds.length}个会话`);
  refreshTable();
}

/**
 * 刷新表格和统计数据
 */
function refreshTable() {
  proTable.value?.refresh();
  statsCardRef.value?.getStats();
}

// 定时刷新表格（每30秒）
onMounted(() => {
  const timer = setInterval(() => {
    refreshTable();
  }, 30000);

  // 组件卸载时清除定时器
  onBeforeUnmount(() => {
    clearInterval(timer);
  });
});
</script>

<style lang="scss" scoped>
.user-info {
  .user-name {
    font-weight: 500;
    color: #303133;
    margin-bottom: 4px;
  }

  .user-account {
    font-size: 12px;
    color: #909399;
  }
}

.login-info {
  .info-item {
    display: flex;
    align-items: center;
    gap: 5px;
    margin-bottom: 4px;
    font-size: 13px;
    color: #606266;

    &:last-child {
      margin-bottom: 0;
    }

    .el-icon {
      font-size: 14px;
      color: #909399;
    }
  }
}

.user-info {
  display: flex;
  align-items: center;
  gap: 12px;

  .user-detail {
    flex: 1;

    .user-name {
      font-weight: 500;
      color: #303133;
      margin-bottom: 4px;
    }

    .user-account {
      font-size: 12px;
      color: #909399;
    }
  }
}

:deep(.el-tag) {
  .is-loading {
    margin-right: 4px;
  }
}
</style>
